package com.example.demo.config.task;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import javax.annotation.Resource;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * @author huangke
 * <p>
 *     替代spring默认的异步线程池配置
 *     默认情况下不会初始化此线程池
 *     当项目中有使用到默认线程池则会先初始化此线程池
 *     例如 {@link org.springframework.scheduling.annotation.Async}并且未指定线程池的情况
 * </p>
 * @date 2020/12/25
 */
@Configuration
public class DefaultTaskExecutorConfig implements AsyncConfigurer {

//    @Resource
//    private CustomerTaskExecutorBuilder.CustomerTaskExecutorProperties customerTaskExecutorProperties;
    @Resource
    private CustomerTaskExecutorBuilder builder;

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = builder.taskExecutorBuilder(getDuoDianTaskProperties1()).build();
        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
        /**
         * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
         * ThreadPoolExecutor.DiscardPolicy：也是丢弃任务，但是不抛出异常。
         * ThreadPoolExecutor.DiscardOldestPolicy：丢弃队列最前面的任务，然后重新尝试执行任务（重复此过程）
         * ThreadPoolExecutor.CallerRunsPolicy：由调用线程处理该任务
         **/
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //执行初始化
        executor.afterPropertiesSet();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }

    @Bean("customerProperties")
    public CustomerCustomerTaskProperties getDuoDianTaskProperties1() {
        return new CustomerCustomerTaskProperties();
    }

    @EqualsAndHashCode(callSuper = true)
    @ConfigurationProperties(prefix = "spring.task.execution")
    @Data
    static class CustomerCustomerTaskProperties extends CustomerTaskExecutorBuilder.CustomerTaskExecutorProperties {
    }

}